package com.tsfyun.scm.service.impl.order;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.dto.TaskDTO;
import com.tsfyun.common.base.enums.domain.*;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.security.SecurityUtil;
import com.tsfyun.common.base.support.DomainStatus;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.base.DataCalling;
import com.tsfyun.scm.dto.order.ExpOrderPricePlusVo;
import com.tsfyun.scm.dto.order.ExpOrderPriceQTO;
import com.tsfyun.scm.dto.support.TaskNoticeContentDTO;
import com.tsfyun.scm.entity.order.*;
import com.tsfyun.scm.mapper.order.ExpOrderPriceMapper;
import com.tsfyun.scm.service.common.ICommonService;
import com.tsfyun.scm.service.order.*;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.service.support.ITaskNoticeContentService;
import com.tsfyun.scm.service.system.IStatusHistoryService;
import com.tsfyun.scm.vo.order.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 *
 * @since 2021-09-14
 */
@Service
public class ExpOrderPriceServiceImpl extends ServiceImpl<ExpOrderPrice> implements IExpOrderPriceService {

    @Autowired
    private ExpOrderPriceMapper expOrderPriceMapper;
    @Autowired
    private IExpOrderMemberService expOrderMemberService;
    @Autowired
    private IExpOrderPriceMemberService expOrderPriceMemberService;
    @Autowired
    private IPriceFluctuationHistoryExpService priceFluctuationHistoryExpService;
    @Autowired
    private IStatusHistoryService statusHistoryService;
    @Autowired
    private Snowflake snowflake;
    @Autowired
    private ICommonService commonService;
    @Autowired
    private IExpOrderService expOrderService;
    @Autowired
    private ITaskNoticeContentService taskNoticeContentService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void calculatingPrice(ExpOrder order) {
        calculatingPrice(order,Boolean.FALSE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void calculatingPrice(ExpOrder order, Boolean isForce) {
        //订单处于待审价状态不需要计算
        if(!Objects.equals(ExpOrderStatusEnum.WAIT_PRICE, ExpOrderStatusEnum.of(order.getStatusId()))){return;}
        Boolean examinePrice = false;//是否需要审价
        Boolean isChange = false;//与上次对比客户是否修改了数据
        if(isForce){//强制审价
            examinePrice = true;
            isChange = true;
        }
        LocalDateTime nowTime = LocalDateTime.now();
        //计算6个月的订单数据
        LocalDateTime startTime = LocalDateTime.now().plusMonths(-6);
        //获取订单明细
        List<ExpOrderMember> expOrderMemberList = expOrderMemberService.getByOrderId(order.getId());
        List<PriceFluctuationHistoryExp> allHistoryList = Lists.newArrayList();
        List<ExpOrderPriceMember> orderPriceMemberList = Lists.newArrayList();

        Long orderPriceId = snowflake.nextId();
        for(ExpOrderMember iom : expOrderMemberList){
            ExpOrderPriceMember iopm = new ExpOrderPriceMember();
            iopm.setId(snowflake.nextId());

            //查询历史出口记录
            List<PriceFluctuationHistoryExp> historyList = expOrderMemberService.findExpHistory(startTime,iom.getModel(),iom.getBrand(),iom.getName(),iom.getSpec());
            BigDecimal totalPrice = BigDecimal.ZERO;//总美金金额
            BigDecimal totalQuantity = BigDecimal.ZERO;//总数量
            if(CollUtil.isNotEmpty(historyList)){
                for(PriceFluctuationHistoryExp priceFluctuationHistory : historyList){
                    PriceFluctuationHistoryExp history = beanMapper.map(priceFluctuationHistory,PriceFluctuationHistoryExp.class);
                    history.setUsdTotalPrice(DataCalling.convertUSDAmount(history.getOrderDate(),history.getCurrencyId(),history.getTotalPrice()));
                    BigDecimal quantity = history.getQuantity();//数量
                    if(history.getUnitName().startsWith("十")){
                        quantity = quantity.multiply(BigDecimal.valueOf(10));
                    }else if(history.getUnitName().startsWith("百")){
                        quantity = quantity.multiply(BigDecimal.valueOf(100));
                    }else if(history.getUnitName().startsWith("千")){
                        quantity = quantity.multiply(BigDecimal.valueOf(1000));
                    }else if(history.getUnitName().startsWith("万")){
                        quantity = quantity.multiply(BigDecimal.valueOf(10000));
                    }else if(history.getUnitName().startsWith("亿")){
                        quantity = quantity.multiply(BigDecimal.valueOf(100000000));
                    }
                    history.setUsdUnitPrice((quantity.compareTo(BigDecimal.ZERO)==1)?history.getUsdTotalPrice().divide(quantity,4,BigDecimal.ROUND_HALF_UP):BigDecimal.ZERO);
                    totalPrice = totalPrice.add(history.getUsdTotalPrice());
                    totalQuantity = totalQuantity.add(quantity);
                    history.setOrderPriceMemberId(iopm.getId());
                    history.setDateCreated(nowTime);
                    history.setId(snowflake.nextId());
                    allHistoryList.add(history);
                }
            }

            iopm.setOrderMemberId(iom.getId());
            iopm.setModel(iom.getModel());
            iopm.setBrand(iom.getBrand());
            iopm.setName(iom.getName());
            iopm.setSpec(iom.getSpec());
            iopm.setUnitCode(iom.getUnitCode());
            iopm.setUnitName(iom.getUnitName());
            iopm.setQuantity(iom.getQuantity());
            iopm.setUnitPrice(iom.getDecUnitPrice());
            iopm.setTotalPrice(iom.getDecTotalPrice());
            iopm.setNetWeight(iom.getNetWeight());
            iopm.setGrossWeight(iom.getGrossWeight());
            iopm.setRowNo(iom.getRowNo());
            //存在出口记录
            if(CollUtil.isNotEmpty(historyList)){
                //平均单价 = 6个月总金额 / 6个月总数量
                BigDecimal avgUnitPrice = totalPrice.divide(totalQuantity,4,BigDecimal.ROUND_HALF_UP);
                //当前订单出口美金金额
                BigDecimal orderTotalPrice = DataCalling.convertUSDAmount(order.getOrderDate(),order.getCurrencyId(),iopm.getTotalPrice());
                BigDecimal orderQuantity = iopm.getQuantity();
                if(iopm.getUnitName().startsWith("十")){
                    orderQuantity = orderQuantity.multiply(BigDecimal.valueOf(10));
                }else if(iopm.getUnitName().startsWith("百")){
                    orderQuantity = orderQuantity.multiply(BigDecimal.valueOf(100));
                }else if(iopm.getUnitName().startsWith("千")){
                    orderQuantity = orderQuantity.multiply(BigDecimal.valueOf(1000));
                }else if(iopm.getUnitName().startsWith("万")){
                    orderQuantity = orderQuantity.multiply(BigDecimal.valueOf(10000));
                }else if(iopm.getUnitName().startsWith("亿")){
                    orderQuantity = orderQuantity.multiply(BigDecimal.valueOf(100000000));
                }
                //波动率=（订单单价 - 平均单价）/ 平均单价
                BigDecimal orderUnitPrice = orderTotalPrice.divide(orderQuantity,4,BigDecimal.ROUND_HALF_UP);
                BigDecimal fluctuations = StringUtils.rounded2((orderUnitPrice.subtract(avgUnitPrice)).divide(avgUnitPrice,4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));
                if(Math.abs(fluctuations.doubleValue()) >= 5){
                    examinePrice = true;//需要审核
                }
                iopm.setFluctuations(fluctuations);
                iopm.setProcessLogs("6个月总金额【"+totalPrice+"】6个月总数量【"+totalQuantity+"】平均单价【"+avgUnitPrice+"】订单单价【"+orderUnitPrice+"】波动率【"+fluctuations+"%】");
                iopm.setIsImp(Boolean.TRUE);
            }else{
                examinePrice = true;//需要审核
                iopm.setFluctuations(BigDecimal.ZERO);
                iopm.setProcessLogs("无出口记录");
                iopm.setIsImp(Boolean.FALSE);
            }

            iopm.setIsNewGoods(Boolean.TRUE);
            iopm.setOrderPriceId(orderPriceId);
            iopm.setCurrencyCode(order.getCurrencyId());
            iopm.setCurrencyName(order.getCurrencyName());
            orderPriceMemberList.add(iopm);

            if(!isChange){
                //查询明细最近一次审价记录-对比数据是否有修改
                Map<String,Object> historyPriceMember = expOrderPriceMemberService.historicalRecord(iom.getId());
                if(Objects.nonNull(historyPriceMember)){
                    if(
                            !Objects.equals(ExpOrderPriceStatusEnum.PASSED,ExpOrderPriceStatusEnum.of(historyPriceMember.get("statusId").toString()))
                                    || !Objects.equals(iopm.getModel(),historyPriceMember.get("model"))
                                    || !Objects.equals(iopm.getBrand(),historyPriceMember.get("brand"))
                                    || !Objects.equals(iopm.getName(),historyPriceMember.get("name"))
                                    || !Objects.equals(iopm.getSpec(),historyPriceMember.get("spec"))
                                    || !Objects.equals(iopm.getQuantity(),historyPriceMember.get("quantity"))
                                    || !Objects.equals(iopm.getUnitPrice(),historyPriceMember.get("unitPrice"))
                                    || !Objects.equals(iopm.getTotalPrice(),historyPriceMember.get("totalPrice"))
                                    || !Objects.equals(iopm.getCurrencyCode(),historyPriceMember.get("currencyCode"))
                    ){
                        isChange = true;
                    }
                }else{
                    isChange = true;
                }
            }
        }
        //数据未修改 不需要审批
        if(!isChange){
            examinePrice = false;
        }
        if(examinePrice){
            ExpOrderPrice orderPrice = new ExpOrderPrice();
            orderPrice.setId(orderPriceId);
            orderPrice.setCustomerId(order.getCustomerId());
            orderPrice.setSupplierId(order.getSupplierId());
            orderPrice.setOrderId(order.getId());
            orderPrice.setOrderDocNo(order.getDocNo());
            ExpOrderPrice queryCount = new ExpOrderPrice();
            queryCount.setOrderId(order.getId());
            ExpOrderPriceStatusEnum statusEnum = ExpOrderPriceStatusEnum.WAIT_EXAMINE;
            orderPrice.setStatusId(statusEnum.getCode());
            orderPrice.setSubmitCount(expOrderPriceMapper.selectCount(queryCount)+1);
            super.save(orderPrice);
            //批量保存明细
            expOrderPriceMemberService.savaBatch(orderPriceMemberList);
            //批量保存明细历史记录
            if(CollUtil.isNotEmpty(allHistoryList)){
                priceFluctuationHistoryExpService.savaBatch(allHistoryList);
            }
            //记录历史状态
            statusHistoryService.saveHistory(DomainOprationEnum.EXP_ORDER_ADD,
                    orderPrice.getId().toString(),ExpOrderPrice.class.getName(),
                    statusEnum.getCode(),statusEnum.getName(),"提交审核"
            );

            //发送任务通知
            TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
            taskNoticeContentDTO.setDocumentType(DomainTypeEnum.EXPORDERPRICE.getCode());
            taskNoticeContentDTO.setDocumentId(orderPrice.getId().toString());
            taskNoticeContentDTO.setCustomerId(orderPrice.getCustomerId());
            taskNoticeContentDTO.setOperationCode(DomainOprationEnum.EXP_ORDER_PRICE_EXAMINE.getCode());
            taskNoticeContentDTO.setContent(String.format("【%s】提交了一单【%s】出口订单需要您审价。", SecurityUtil.getCurrentPersonName(),orderPrice.getOrderDocNo()));
            taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",orderPrice.getOrderDocNo()));
            taskNoticeContentService.add(taskNoticeContentDTO);
        }else{
            TaskDTO orderDTO = new TaskDTO();
            orderDTO.setDocumentId(order.getId());
            orderDTO.setDocumentClass(DomainTypeEnum.EXPORDER.getCode());
            orderDTO.setOperation(DomainOprationEnum.EXP_ORDER_PRICING.getCode());
            orderDTO.setNewStatusCode(ExpOrderStatusEnum.WAIT_EXAMINE.getCode());
            orderDTO.setMemo(isChange?"订单存在历史审价记录,无需再次审价":"价格波动正常,无需再次审价");
            orderDTO.setOperator("系统");
            expOrderService.orderPricing(orderDTO);

            //发送任务通知
            TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
            taskNoticeContentDTO.setDocumentType(DomainTypeEnum.EXPORDER.getCode());
            taskNoticeContentDTO.setDocumentId(order.getId().toString());
            taskNoticeContentDTO.setCustomerId(order.getCustomerId());
            taskNoticeContentDTO.setOperationCode(DomainOprationEnum.EXP_ORDER_EXAMINE.getCode());
            taskNoticeContentDTO.setContent(String.format("【%s】提交了一单【%s】出口订单需要您审核。", SecurityUtil.getCurrentPersonName(),order.getDocNo()));
            taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",order.getDocNo()));
            taskNoticeContentService.add(taskNoticeContentDTO);
        }
    }

    @Override
    public PageInfo<ExpOrderPriceVO> list(ExpOrderPriceQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        List<ExpOrderPriceVO> list = expOrderPriceMapper.list(params);
        return new PageInfo<>(list);
    }

    @Override
    public ExpOrderPricePlusVo detail(Long id) {
        return detail(id,null);
    }

    @Override
    public ExpOrderPricePlusVo detail(Long id, String operation) {
        ExpOrderPrice expOrderPrice = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(expOrderPrice),new ServiceException("审价信息不存,请刷新页面重试"));
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.of(operation), expOrderPrice.getStatusId());
        ExpOrderPriceVO orderPrice = beanMapper.map(expOrderPrice,ExpOrderPriceVO.class);
        List<ExpOrderPriceMemberVO> members = expOrderPriceMemberService.findByOrderPriceId(expOrderPrice.getId());
        return new ExpOrderPricePlusVo(orderPrice,members);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void examine(TaskDTO dto) {
        ExpOrderPrice expOrderPrice = commonService.changeDocumentStatus(dto);
        ExpOrderPriceStatusEnum statusEnum = ExpOrderPriceStatusEnum.of(expOrderPrice.getStatusId());
        TaskDTO orderDTO = new TaskDTO();
        switch (statusEnum){
            case PASSED://已通过
                orderDTO.setNewStatusCode(ExpOrderStatusEnum.WAIT_EXAMINE.getCode());
                ExpOrderPrice update = new ExpOrderPrice();
                update.setReviewer(SecurityUtil.getCurrentPersonName());
                update.setReviewTime(new Date());
                expOrderPriceMapper.updateByExampleSelective(update, Example.builder(ExpOrderPrice.class).where(WeekendSqls.<ExpOrderPrice>custom()
                        .andEqualTo(ExpOrderPrice::getId, expOrderPrice.getId())).build());
                break;
            case RETURNED://已退回
                orderDTO.setNewStatusCode(ExpOrderStatusEnum.WAIT_EDIT.getCode());
                break;
            default:
                throw new ServiceException("状态错误");
        }
        orderDTO.setDocumentId(expOrderPrice.getOrderId());
        orderDTO.setDocumentClass(DomainTypeEnum.EXPORDER.getCode());
        orderDTO.setOperation(DomainOprationEnum.EXP_ORDER_PRICING.getCode());
        orderDTO.setMemo(dto.getMemo());
        expOrderService.orderPricing(orderDTO);

        //发送任务通知
        TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
        taskNoticeContentDTO.setDocumentType(DomainTypeEnum.EXPORDER.getCode());
        taskNoticeContentDTO.setDocumentId(expOrderPrice.getOrderId().toString());
        taskNoticeContentDTO.setCustomerId(expOrderPrice.getCustomerId());
        if(Objects.equals(ExpOrderPriceStatusEnum.RETURNED,statusEnum)){//已退回
            taskNoticeContentDTO.setOperationCode(DomainOprationEnum.EXP_ORDER_EDIT.getCode());
            taskNoticeContentDTO.setContent(String.format("出口订单【%s】审价被退回：%s", expOrderPrice.getOrderDocNo(),dto.getMemo()));
        }else{//已通过
            taskNoticeContentDTO.setOperationCode(DomainOprationEnum.EXP_ORDER_EXAMINE.getCode());
            taskNoticeContentDTO.setContent(String.format("出口订单【%s】审价已通过，请确认。", expOrderPrice.getOrderDocNo()));
        }
        taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",expOrderPrice.getOrderDocNo()));
        taskNoticeContentService.add(taskNoticeContentDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeByOrderId(Long orderId) {
        expOrderPriceMemberService.removeByOrderId(orderId);
        expOrderPriceMapper.removeByOrderId(orderId);
    }
}
